package com.androidtest3d.math;

/**
 * Android Game Tutorial Project.
 *
 * Copyright (C) 2011  Philipp Jenke
 * 
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 * 
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

/**
 * Representation of a symetric matrix.
 */
public class MyMatrix {
	/**
	 * Dimension of the matrix.
	 */
	private final int dimension;

	/**
	 * Entries of the matrix
	 */
	private final MyVector rows[];

	/**
	 * Constructor.
	 * 
	 * @param d
	 */
	public MyMatrix(final int d) {
		dimension = d;
		rows = new MyVector[d];
		for (int i = 0; i < d; i++) {
			rows[i] = new MyVector(d);
		}

	}

	/**
	 * Set the row 'index'.
	 * 
	 * @param index
	 * @param row
	 * @throws Exception
	 */
	public void setRow(final int index, MyVector row)
			throws DimensionsNotMatchException {
		if (row.getDimension() != dimension) {
			throw new DimensionsNotMatchException("Dimensions do not match.");
		}
		rows[index].copyFrom(row);
	}

	/**
	 * Create a 3x3 matrix.
	 * 
	 * @param row1
	 * @param row2
	 * @return
	 * @throws Exception
	 */
	public static MyMatrix makeMatrix3(final MyVector row1,
			final MyVector row2, final MyVector row3)
			throws DimensionsNotMatchException {
		MyMatrix result = new MyMatrix(MathHelpers.getDimension3());
		result.setRow(0, row1);
		result.setRow(1, row2);
		result.setRow(2, row3);
		return result;
	}

	/**
	 * Create a rotation matrix around an axis with a given angle.
	 * 
	 * @param axis
	 * @param angle
	 * @return
	 * @throws Exception
	 */
	public static MyMatrix getRotationMatrix(MyVector axis, double angle)
			throws DimensionsNotMatchException {
		if (MathHelpers.getDimension3() != axis.getDimension()) {
			throw new DimensionsNotMatchException("Dimensions do not match.");
		}

		double s = Math.sin(angle);
		double c = Math.cos(angle);
		double t = 1.0 - c;

		return MyMatrix.makeMatrix3(MyVector.makeVector3(
				t * axis.get(0) * axis.get(0) + c,
				t * axis.get(0) * axis.get(1) + s * axis.get(2),
				t * axis.get(0) * axis.get(2) - s * axis.get(1)), MyVector
				.makeVector3(t * axis.get(0) * axis.get(1) - s * axis.get(2), t
						* axis.get(1) * axis.get(1) + c,
						t * axis.get(1) * axis.get(2) + s * axis.get(0)),
				MyVector.makeVector3(
						t * axis.get(0) * axis.get(2) + s * axis.get(1), t
								* axis.get(2) * axis.get(2) - s * axis.get(0),
						t * axis.get(2) * axis.get(2) + c));

		/*
		 * float s = sin(angle); float c = cos(angle); float t = 1 - c; return
		 * makeMatrix3f(t * v[0] * v[0] + c, t * v[0] * v[1] + s * v[2], t v[0]
		 * * v[2] - s * v[1], t * v[0] * v[1] - s * v[2], t * v[1] v[1] + c, t *
		 * v[1] * v[2] + s * v[0], t * v[0] * v[2] + s v[1], t * v[2] * v[2] - s
		 * * v[0], t * v[2] * v[2] + c);
		 */
	}

	/**
	 * Compute the product of this matrix and a vector.
	 * 
	 * @param other
	 * @return
	 * @throws Exception
	 */
	public MyVector multiply(final MyVector other)
			throws DimensionsNotMatchException {
		MyVector result = new MyVector(dimension);
		if (other.getDimension() != dimension) {
			throw new DimensionsNotMatchException("Dimensions do not match.");
		}

		for (int i = 0; i < dimension; i++) {
			result.set(i, getRow(i).multiply(other));
		}

		return result;
	}

	/**
	 * Getter.
	 * 
	 * @param index
	 * @return
	 */
	public MyVector getRow(final int index) {
		return rows[index];
	}
}
